// trait 作为参数
// @author 风杨
// @date 22-9-8 下午5:46
// @see <a href="yueny09@163.com">mailTo: yueny09@163.com</a>
//

use std::fmt::Display;
use crate::{ISummary, Tweet};
use crate::r#trait::summary::NewsArticle;

pub fn args(){
    println!("################### args ##################");

    let tweet = returns_Tweet();

    let article = NewsArticle {
        headline: String::from("NewsArticle"),
        location: String::from(
            "of course, as you probably already know, people",
        ),
        author: String::from("horse_ebooks"),
        content: String::from("horse_ebooks"),
    };

    println!("go: {}", tweet.go());
    println!("go: {}", article.go());

    // tweet not have clone
    // article have clone: article.clone();
    notify(&tweet);
    notify(&article);

    let te = Tweet::from(article);
    notify(&te);

    notify_(&tweet);
    notify_where(&tweet);
}

// 对于 item 参数，我们指定了 impl 关键字和 trait 名称，而不是具体的类型。
// 该参数支持任何实现了指定 trait 的类型。
pub fn notify(item: &impl ISummary) {
    // ==> Trait Bound 语法
    // 等价于
    // pub fn notify<T: Summary>(item: &T) {
    // 在 notify 函数体中，可以调用任何来自 Summary trait 的方法
    println!("notify Breaking news! {}", item.summarize());
}

// 通过 + 指定多个 trait bound
pub fn notify_(item: &(impl ISummary + Display)) {
    // 如果 notify 需要显示 item 的格式化形式，同时也要使用 summarize 方法，
    // 那么 item 就需要同时实现两个不同的 trait：Display 和 Summary。这可以通过 + 语法实现
    println!("notify+ Breaking news! {}", item.summarize());
}


// 通过 where 简化 多个 trait bound
pub fn notify_where<T>(item: &T) where T: ISummary + Display
{
    // 如果 notify 需要显示 item 的格式化形式，同时也要使用 summarize 方法，
    // 那么 item 就需要同时实现两个不同的 trait：Display 和 Summary。这可以通过 + 语法实现
    println!("notify+_where Breaking news! {}", item.summarize());
}

/// 返回实现了 trait 的类型,  但是不确定其具体的类型。
/// 只适用于返回单一类型的情况, 如果根据不同的条件可能返回 Tweet 或者 NewsArticle ， 是不允许的
fn returns_Tweet() -> impl ISummary + Display {
    let tweet = Tweet {
        username: String::from("Tweet"),
        content: String::from(
            "of course, as you probably already know, people",
        ),
        reply: false,
        retweet: false,
    };

    tweet
}